; Copyright (C) 2021 Rain

; This file is part of XNIX. 
; XNIX is free software: you can redistribute it and/or modify 
; it under the terms of the GNU General Public License as published by 
; the Free Software Foundation, either version 3 of the License, or 
; (at your option) and later version. 

; XNIX is distributed in the hope that it will be useful, 
; but WITHOUT ANY WARRANTY; without even the implied warranty of 
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
; GNU General Public License for more details. 

; You should have received a copy of the GNU General Public License 
; along with XNIX. If not, see <https://www.gnu.org/licenses/>.  




org 0x7c00

cyldsneed equ 10


; yeah, it's really 0x7c00 because I don't want to use other memory. 

BOOTDRIVER 	equ 0x7c00
VMODE	 	equ 0x7c01
SCREENX 	equ 0x7c02
SCREENY 	equ 0x7c04
FB_ADDR 	equ 0x7c06
CURSORX 	equ 0x7c0a
CURSORY 	equ 0x7c0b
COM0 		equ 0x7c0c
COM1 		equ 0x7c0e
COM2 		equ 0x7c10
COM3 		equ 0x7c12


_start:
	xor ax, ax

	mov ds, ax
	mov es, ax

	mov ss, ax
	mov sp, 0x7c00

	; save startup driver
	mov [BOOTDRIVER], dl

	; display message 'Loading System'

	mov si, boot_msg
	call print

	call read_sb

	; get e820 memory

	xor ebx, ebx

	; yeah, we used it in .set_vga. 
	; and I think this is a good place (no one used it)

	xor ax, ax
	mov es, ax

	mov di, 0x7000

.get_loop:
	mov eax, 0x0000e820
	mov ecx, 20
	mov edx, 0x534d4150

	int 0x15

	jc .get_failed

	add di, 20

	cmp ebx, 0
	jne .get_loop

.serial_init:
	; get serial ports, and save it to bootarg
	mov ax, [0x400]
	mov [COM0], ax

	mov ax, [0x402]
	mov [COM1], ax

	mov ax, [0x404]
	mov [COM2], ax

	mov ax, [0x406]
	mov [COM3], ax

	; jump to loader, 3488 bytes max 
	jmp 0x0000:0x7e60

.get_failed:
	mov si, e820_fail_msg
	call print

.die:	hlt
	jmp .die


print:
	cld
	lodsb

	test al,al
	jz .ret

	mov ah, 0x0e
	mov bx, 0x0f
	int 0x10

	jmp print

.ret:
	ret


; load the first block (4096 bytes)

read_sb:
	; we try LBA first because some disks supports wrong CHS. (bad sector per track)
	; if this boot disk doesn't support LBA mode, it should be a floppy. 
	mov ax, 0x07e0
	mov es, ax

	mov ax, 1
	mov cl, 1
	xor bx, bx

	call read_lba
	
	jc read_failed

using_lba:
	; put message on screen
	mov si, lamsg
	call print

	; the first sector (LBA address starts at 0) read, 
	; so we read start at address 1
	
	; and we should add address

	mov ax, 0x07e0
	mov es, ax

	mov ax, 1

.read_loop:
	mov bx, es
	add bx, 512 / 16
	mov es, bx

	inc ax

	mov cl, 1

	xor bx, bx

	call read_lba
	
	; 8 sectors = 4KB

	cmp ax, 8
	jb .read_loop

	ret


read_failed:
	mov si, read_fail_msg
	call print

.die:	hlt
	jmp .die


read_lba:
	pushaw

	push dword 0x0000
	push dword eax

	; buffer address
	push word es
	push word bx

	; sectors count
	push word cx

	; package size
	push word 16

	mov ah, 0x42
	mov dl, [BOOTDRIVER]
	mov si, sp

	int 0x13

	add sp, 16
	
	popaw

	ret


boot_msg: db "Loading System...", 0x0d, 0x0a, 0x00
read_fail_msg: db "panic: read disk failed. ", 0x0d, 0x0a, 0x00
lamsg: db "LBA mode is avaliable. ", 0x0d, 0x0a, 0x00
e820_fail_msg: db "panic: read E820 memory info failed. ", 0x0d, 0x0a, 0x00


times 510 - ($ - $$) db 0x00
db 0x55, 0xaa

